package org.ccay.download.servlet;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.ccay.audit.service.ILogService;
import org.ccay.audit.vo.LogVO;
import org.ccay.core.exception.ApplicationException;
import org.ccay.core.io.VFSFileObject;
import org.ccay.core.ioc.Ccay;
import org.ccay.core.log.CcayLoggerFactory;
import org.ccay.core.log.ILogger;
import org.ccay.core.util.CollectionUtil;
import org.ccay.core.util.FileUtil;
import org.ccay.core.util.MimeTypeUtil;
import org.ccay.core.util.StringUtil;
import org.ccay.download.DownloadException;
import org.ccay.download.IDownloadSupport;
import org.ccay.download.httpdownload.DownloadOutput;


/**
 * 下载Servlet，受Spring管理
 */
@Named("/servlet/download")
public class DownloadServlet extends HttpServlet {	
	
	private ILogger log = CcayLoggerFactory.getLogger(DownloadServlet.class);
	private static final long serialVersionUID = 2315696463238122275L;
	
	@Inject
	private ILogService logService;
	/**
	 * 下载组件提供的下载对象
	 */
	private static DownloadOutput download = new DownloadOutput();
	

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
		HttpServletRequest httpRequest = (HttpServletRequest)request;
		HttpServletResponse httpResponse = (HttpServletResponse)response;
		
		request.setAttribute("CCAY_IS_HTML", true );
		//重写Header
		httpResponse.setHeader("Pragma", "private");
		httpResponse.setHeader("Cache-Control", "private");
		Map<String,String>  parameters = CollectionUtil.convert(request.getParameterMap());
		//获取下载类型
		String dlType = parameters.get("dlType");
		
		log.debug("Now processing download for type:{0}, Bean named {1} will be used." , 
				dlType, "IDownloadSupport." + dlType);
		
		try {
			processDownload(httpRequest, httpResponse, parameters, dlType);
		} catch (ApplicationException e) {
			throw new ServletException(e);
		}		
	}

	
	/** 
	 * 处理下载
	 * @param req
	 * @param resp
	 * @param parameters
	 * @param dlType
	 * @throws ApplicationException 
	 * @throws IOException 
	 */
	private void processDownload(HttpServletRequest req, HttpServletResponse resp, Map<String, String> parameters, String dlType) throws ApplicationException, IOException {
		//获取对应的下载支持
		IDownloadSupport dls = getDownloadSupport(dlType);
		//验证权限
		if(!dls.validatePrivilege(parameters)){
			throw new DownloadException("ccay.security.00010001");
		}
		//获取待下载文件
		VFSFileObject file = dls.getFileInfo(parameters);
		sendlogMessage(parameters.get("dlType"), file);
		sendContentType(req, file);
		downloadOutput(req, resp, file);
	}
	/** 
	 * 发送内容类型
	 * @param req
	 * @param file
	 */
	private void sendContentType(HttpServletRequest req, VFSFileObject file) {
		req.setAttribute("DownloadInline",file.isInline());
		
		String contentType = file.getContentType();
		
		if(!StringUtil.isNullOrEmpty(contentType)){
			req.setAttribute("DownloadContentType", contentType);
			return;
		}
		
		String ext = FileUtil.getExtension(file.getDisplayName());			
		contentType = MimeTypeUtil.getTypeBySuffix(ext);
		
		if(!StringUtil.isNullOrEmpty(contentType)){
			req.setAttribute("DownloadContentType", contentType);
		}
	}


	/**
	 * 发送记录日志的消息
	 * @param message
	 * @throws ApplicationException 
	 */
	private void sendlogMessage(String type,VFSFileObject file) throws ApplicationException{
		//文件权限验证通过后，执行操作日志 并下载
		LogVO logMessage = new LogVO();
		logMessage.buildAotoAttribute();
		// 操作所属的类
		logMessage.setClazz("DownloadServlet");
		logMessage.setOperation("Download");
		logMessage.setLogType(0);
		logMessage.setModule(type + " Download");
		logMessage.setOperateObject(file.getDisplayName());
		try {
			logMessage.setServerName(InetAddress.getLocalHost().getHostName());
		} catch (UnknownHostException e) {
			logMessage.setServerName("");
		}
		logMessage.setMessage("download file name is " + file.getDisplayName());
		logService.asyncCreateLog(logMessage);
	}
	
	/**
	 * 执行下载
	 * @param req
	 * @param resp
	 * @param file
	 * @throws DownloadException
	 */
	private void downloadOutput(HttpServletRequest req, HttpServletResponse resp, VFSFileObject file) throws DownloadException {
		InputStream in =  null;
		try {
			//尝试下载文件
			
			String agent = req.getHeader("User-Agent").toLowerCase();
			in = file.getInputStream();
			if(in != null){
				//根据浏览器判断下载文件名转义  
				String displayName = file.getDisplayName();
				boolean autoFormat = true;
				//根据浏览器判断下载文件名转义 
				if(!(agent.indexOf("msie") != -1 || agent.indexOf("trident") != -1)){
					displayName = new String(displayName.getBytes("UTF-8"),"ISO8859-1");
					autoFormat = false;
				}
				download.outputFromStream(req, resp, in, displayName, autoFormat, file.getSize());
				return;
			}
//			IOutputAction action = file.getOutputAction();
//			out = resp.getOutputStream();
//			if(action != null){
//				setHttpHeaders(resp, file);
//				action.doOutput(out);
//			}
		} catch(FileNotFoundException e){
			throw new DownloadException("ccay.download.support.00010002",e);
		} catch (Exception e) {
			throw new DownloadException("ccay.download.support.00010001",e);
		} finally{		
			try {
				in.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			file.close();
		}
	}
	
//	/** 
//	 * 设置参数
//	 * @param req
//	 * @param resp
//	 * @param file
//	 */
//	private void setHttpHeaders(HttpServletResponse resp, VFSFileObject file) {
//		String header = file.isInline() ? "inline; " : "attachment; ";
//		header = header + "filename=\"" + file.getDisplayName() + "\"";
//		resp.setHeader("Content-Disposition", header);
//	}

	/** 
	 * 基于规则寻找 IDownloadSupport 实现
	 * @param dlType
	 * @return
	 */
	private IDownloadSupport getDownloadSupport(String dlType) {
		return Ccay.getContext().getBean("IDownloadSupport." + dlType , IDownloadSupport.class);
	}	
	 
	 
}
